home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / dc-0_2.lha / dc-0.2 / dc.c < prev    next >
C/C++ Source or Header  |  1993-05-19  |  18KB  |  910 lines

  1. /* 
  2.  * `dc' desk calculator utility.
  3.  *
  4.  * Copyright (C) 1984, 1993 Free Software Foundation, Inc.
  5.  *
  6.  * This program is free software; you can redistribute it and/or modify
  7.  * it under the terms of the GNU General Public License as published by
  8.  * the Free Software Foundation; either version 2, or (at your option)
  9.  * any later version.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program; if not, you can either send email to this
  18.  * program's author (see below) or write to: The Free Software Foundation,
  19.  * Inc.; 675 Mass Ave. Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include "decimal.h"  /* definitions for our decimal arithmetic package */
  24.  
  25. FILE *open_file;    /* input file now open */
  26. int file_count;        /* Number of input files not yet opened */
  27. char **next_file;    /* Pointer to vector of names of input files left */
  28.  
  29. struct regstack
  30.   {
  31.     decimal value;    /* Saved value of register */
  32.     struct regstack *rest;    /* Tail of list */
  33.   };
  34.  
  35. typedef struct regstack *regstack;
  36.  
  37. regstack freeregstacks;    /* Chain of free regstack structures for fast realloc */
  38.  
  39. decimal regs[128];    /* "registers", with single-character names */
  40. regstack regstacks[128]; /* For each register, a stack of previous values */
  41.  
  42. int stacktop;        /* index of last used element in stack */
  43. int stacksize;        /* Current allocates size of stack */
  44. decimal *stack;    /* Pointer to computation stack */
  45.  
  46. /* A decimal number can be regarded as a string by
  47.  treating its contents as characters and ignoring the
  48.  position of its decimal point.
  49.  Decimal numbers are marked as strings by having an `after' field of -1
  50.  One use of strings is to execute them as macros.
  51. */
  52.  
  53. #define STRING -1
  54.  
  55. int macrolevel;    /* Current macro nesting; 0 if taking keyboard input */
  56. int macrostacksize;    /* Current allocated size of macrostack and macroindex */
  57. decimal *macrostack;    /* Pointer to macro stack array */
  58. int *macroindex;    /* Pointer to index-within-macro stack array */
  59.     /* Note that an empty macro is popped from the stack
  60.        only when an trying to read a character from it
  61.        or trying to push another macro.  */
  62.  
  63. int ibase;    /* Radix for numeric input.  */
  64. int obase;    /* Radix for numeric output.  */
  65. int precision;    /* Number of digits to keep in multiply and divide.  */
  66.  
  67. char *buffer;    /* Address of buffer used for reading numbers */
  68. int bufsize;    /* Current size of buffer (made bigger when nec) */
  69.  
  70. decimal dec_read ();
  71. regstack get_regstack ();
  72. int fetch ();
  73. int fgetchar ();
  74. char *concat ();
  75. void pushsqrt ();
  76. void condop ();
  77. void setibase ();
  78. void setobase ();
  79. void setprecision ();
  80. void pushmacro ();
  81. decimal read_string ();
  82. void pushlength ();
  83. void pushscale ();
  84. void unfetch ();
  85. void popmacros ();
  86. void popmacro ();
  87. void popstack ();
  88. void print_obj ();
  89. void print_string ();
  90. void free_regstack ();
  91. void pushreg ();
  92. void execute ();
  93. void fputchar ();
  94. void push ();
  95. void incref ();
  96. void decref ();
  97. void binop ();
  98.  
  99. main (argc, argv, env)
  100.      int argc;
  101.      char **argv, **env;
  102. {
  103.  
  104.   ibase = 10;
  105.   obase = 10;
  106.   precision = 0;
  107.  
  108.   freeregstacks = 0;
  109.  
  110.   bzero (regs, sizeof regs);
  111.   bzero (regstacks, sizeof regstacks);
  112.  
  113.   bufsize = 40;
  114.   buffer = (char *) xmalloc (40);
  115.  
  116.   stacksize = 40;
  117.   stack = (decimal *) xmalloc (stacksize * sizeof (decimal));
  118.   stacktop = -1;
  119.  
  120.   macrostacksize = 40;
  121.   macrostack = (decimal *) xmalloc (macrostacksize * sizeof (decimal));
  122.   macroindex = (int *) xmalloc (macrostacksize * sizeof (int));
  123.   macrolevel = 0;
  124.   /* Initialize for reading input files if any */
  125.  
  126.   open_file = 0;
  127.  
  128.   file_count = argc - 1;
  129.   next_file = argv + 1;
  130.  
  131.  
  132.   while (1)
  133.     {
  134.       execute ();
  135.     }
  136. }
  137.  
  138. /* Read and execute one command from the current source of input */
  139.  
  140. void
  141. execute ()
  142. {
  143.   int c = fetch ();
  144.  
  145.   if (c < 0) exit (0);
  146.  
  147.     {
  148.       switch (c)
  149.     {
  150.     case '+':        /* Arithmetic operators... */
  151.       binop (decimal_add);
  152.       break;
  153.  
  154.     case '-':
  155.       binop (decimal_sub);
  156.       break;
  157.  
  158.     case '*':
  159.       binop (decimal_mul_dc);  /* Like decimal_mul but hairy
  160.                       way of deciding precision to keep */
  161.       break;
  162.  
  163.     case '/':
  164.       binop (decimal_div);
  165.       break;
  166.  
  167.     case '%':
  168.       binop (decimal_rem);
  169.       break;
  170.  
  171.     case '^':
  172.       binop (decimal_expt);
  173.       break;
  174.  
  175.     case '_':        /* Begin a negative decimal constant */
  176.       {
  177.         decimal tem = dec_read (stdin);
  178.         tem->sign = !tem->sign;
  179.         push (tem);
  180.       }
  181.       break;
  182.  
  183.     case '.':
  184.     case '0':
  185.     case '1':
  186.     case '2':
  187.     case '3':
  188.     case '4':
  189.     case '5':
  190.     case '6':
  191.     case '7':
  192.     case '8':
  193.     case '9':        /* All these begin decimal constants */
  194.       unfetch (c);
  195.       push (dec_read (stdin));
  196.       break;
  197.  
  198.     case 'A':
  199.     case 'B':
  200.     case 'C':
  201.     case 'D':
  202.     case 'E':
  203.     case 'F':
  204.       unfetch (c);
  205.       push (dec_read (stdin));
  206.       break;
  207.  
  208.     case 'c':        /* Clear the stack */
  209.       while (stacktop >= 0)
  210.         decref (stack[stacktop--]);
  211.       break;
  212.  
  213.     case 'd':        /* Duplicate top of stack */
  214.       if (stacktop < 0)
  215.         error ("stack empty", 0);
  216.       else push (stack[stacktop]);
  217.       break;
  218.  
  219.     case 'f':        /* Describe all registers and stack contents */
  220.       {
  221.         int regno;
  222.         int somereg = 0;    /* set to 1 if we print any registers */
  223.         for (regno = 0; regno < 128; regno++)
  224.           {
  225.         if (regs[regno])
  226.           {
  227.             printf ("register %c: ", regno);
  228.             print_obj (regs[regno]);
  229.             somereg = 1;
  230.             printf ("\n");
  231.           }
  232.           }
  233.         if (somereg)
  234.           printf ("\n");
  235.         if (stacktop < 0)
  236.           printf ("stack empty\n");
  237.         else
  238.           {
  239.         int i;
  240.         printf ("stack:\n");
  241.         for (i = 0; i <= stacktop; i++)
  242.           {
  243.             print_obj (stack[stacktop - i]);
  244.             printf ("\n");
  245.           }
  246.           }
  247.       }
  248.       break;
  249.  
  250.     case 'i':        /* ibase <- top of stack */
  251.       popstack (setibase);
  252.       break;
  253.  
  254.     case 'I':        /* Push current ibase */
  255.       push (decimal_from_int (ibase));
  256.       break;
  257.  
  258.     case 'k':        /* like i, I but for precision instead of ibase */
  259.       popstack (setprecision);
  260.       break;
  261.  
  262.     case 'K':
  263.       push (decimal_from_int (precision));
  264.       break;
  265.  
  266.     case 'l':        /* l<x> load register <x> onto stack */
  267.       {
  268.         char c1 = fetch ();
  269.         if (c1 < 0) exit (0);
  270.         if (!regs[c1])
  271.           error ("register %c empty", c1);
  272.         else
  273.           push (regs[c1]);
  274.       }
  275.       break;
  276.  
  277.     case 'L':        /* L<x> load register <x> to stack, pop <x>'s own stack */
  278.       {
  279.         char c1 = fetch ();
  280.         if (c1 < 0) exit (0);
  281.         if (!regstacks[c1])
  282.           error ("nothing pushed on register %c", c1);
  283.         else
  284.           {
  285.         regstack r = regstacks[c1];
  286.         if (!regs[c1])
  287.           error ("register %c empty after pop", c1);
  288.         else
  289.           push (regs[c1]);
  290.         regs[c1] = r->value;
  291.         regstacks[c1] = r->rest;
  292.         free_regstack (r);
  293.           }
  294.       }
  295.       break;
  296.  
  297.     case 'o':        /* o, O like i, I but for obase instead of ibase */
  298.       popstack (setobase);
  299.       break;
  300.  
  301.     case 'O':
  302.       push (decimal_from_int (obase));
  303.       break;
  304.  
  305.     case 'p':        /* Print tos, don't pop, do print newline afterward */
  306.       if (stacktop < 0)
  307.         error ("stack empty", 0);
  308.       else
  309.         {
  310.           print_obj (stack[stacktop]);
  311.           printf ("\n");
  312.         }
  313.       break;
  314.  
  315.     case 'P':        /* Print tos, do pop, no newline afterward */
  316.       popstack (print_obj);
  317.       break;
  318.  
  319.     case 'q':        /* Exit */
  320.       if (macrolevel)
  321.         { popmacro (); popmacro (); }  /* decrease recursion level by 2 */
  322.       else
  323.         exit (0);        /* If not in a macro, exit the program.  */
  324.  
  325.       break;
  326.  
  327.     case 'Q':        /* Tos says how many levels to exit */
  328.       popstack (popmacros);
  329.       break;
  330.  
  331.     case 's':        /* s<x> -- Pop stack and set register <x> */
  332.       if (stacktop < 0)
  333.         empty ();
  334.       else
  335.         {
  336.           int c1 = fetch ();
  337.           if (c1 < 0) exit (0);
  338.           if (regs[c1]) decref (regs[c1]);
  339.           regs[c1] = stack[stacktop--];
  340.         }
  341.       break;
  342.  
  343.     case 'S':        /* S<x> -- pop stack and push as new value of register <x> */
  344.       if (stacktop < 0)
  345.         empty ();
  346.       else
  347.         {
  348.           int c1 = fetch ();
  349.           if (c1 < 0) exit (0);
  350.           pushreg (c1);
  351.           regs[c1] = stack[stacktop--];
  352.         }
  353.       break;
  354.  
  355.     case 'v':        /* tos gets square root of tos */
  356.       popstack (pushsqrt);
  357.       break;
  358.  
  359.     case 'x':        /* pop stack , call as macro */
  360.       popstack (pushmacro);
  361.       break;
  362.  
  363.     case 'X':        /* Pop stack, get # fraction digits, push that */
  364.       popstack (pushscale);
  365.       break;
  366.  
  367.     case 'z':        /* Compute depth of stack, push that */
  368.       push (decimal_from_int (stacktop + 1));
  369.       break;
  370.  
  371.     case 'Z':        /* Pop stack, get # digits, push that */
  372.       popstack (pushlength);
  373.       break;
  374.  
  375.     case '<':        /* Conditional: pop two numbers, compare, maybe execute register */
  376.       /* Note: for no obvious reason, the standard Unix `dc'
  377.          considers < to be true if the top of stack is less
  378.          than the next-to-top of stack,
  379.          and vice versa for >.
  380.          This seems backwards to me, but I am preserving compatibility.  */
  381.       condop (1);
  382.       break;
  383.  
  384.     case '>':
  385.       condop (-1);
  386.       break;
  387.  
  388.     case '=':
  389.       condop (0);
  390.       break;
  391.  
  392.     case '?':        /* Read expression from terminal and execute it */
  393.       /* First ignore any leading newlines */
  394.       {
  395.         int c1;
  396.         while ((c1 = getchar ()) == '\n');
  397.         ungetc (c1, stdin);
  398.       }
  399.       /* Read a line from the terminal and execute it.  */
  400.       pushmacro (read_string ('\n', fgetchar, 0));
  401.       break;
  402.  
  403.     case '[':        /* Begin string constant */
  404.       push (read_string (']', fetch, '['));
  405.       break;
  406.  
  407.         case ' ':
  408.     case '\n':
  409.       break;
  410.  
  411.     default:
  412.       error ("undefined command %c", c);
  413.     }
  414.     }
  415. }
  416.  
  417. /* Functionals for performing arithmetic, etc */
  418.  
  419. /* Call the function `op', with the top of stack value as argument,
  420.  and then pop the stack.
  421.  If the stack is empty, print a message and do not call `op'.  */
  422.  
  423. void
  424. popstack (op)
  425.      void (*op) ();
  426. {
  427.   if (stacktop < 0)
  428.     empty ();
  429.   else
  430.     {
  431.       decimal value = stack[stacktop--];
  432.       op (value);
  433.       decref (value);
  434.     }
  435. }
  436.  
  437. /* Call the function `op' with two arguments taken from the stack top,
  438.  then pop those arguments and push the value returned by `op'.
  439.  `op' is assumed to return a decimal number.
  440.  If there are not two values on the stack, print a message
  441.  and do not call `op'.  */
  442.  
  443. void
  444. binop (op)
  445.      decimal (*op) ();
  446. {
  447.   if (stacktop < 1)
  448.     error ("stack empty", 0);
  449.   else if (stack[stacktop]->after == STRING || stack[stacktop - 1]->after == STRING)
  450.     error ("operands not both numeric");
  451.   else
  452.     {
  453.       decimal arg2 = stack [stacktop--];
  454.       decimal arg1 = stack [stacktop--];
  455.  
  456.       push (op (arg1, arg2, precision));
  457.  
  458.       decref (arg1);
  459.       decref (arg2);
  460.     }
  461. }
  462.  
  463. void
  464. condop (cond)
  465.      int cond;
  466. {
  467.   int regno = fetch ();
  468.   if (!regs[regno])
  469.     error ("register %c is empty", regno);
  470.   else if (stacktop < 1)
  471.     empty ();
  472.   else
  473.     {
  474.       decimal arg2 = stack[stacktop--];
  475.       decimal arg1 = stack[stacktop--];
  476.       int relation = decimal_compare (arg1, arg2);
  477.       decref (arg1);
  478.       decref (arg2);
  479.       if (cond == relation
  480.       || (cond < 0 && relation < 0)
  481.       || (cond > 0 && relation > 0))
  482.     pushmacro (regs[regno]);
  483.     }
  484. }
  485.  
  486. /* Handle the command input source */
  487.  
  488. /* Fetch the next command character from a macro or from the terminal */
  489.  
  490. int
  491. fetch()
  492. {
  493.   int c = -1;
  494.  
  495.   while (macrolevel &&
  496.         LENGTH (macrostack[macrolevel-1]) == macroindex[macrolevel-1])
  497.     popmacro();
  498.   if (macrolevel)
  499.     return macrostack[macrolevel - 1]->contents[macroindex[macrolevel-1]++];
  500.   while (1)
  501.     {
  502.       if (open_file)
  503.     {
  504.       c = getc (open_file);
  505.       if (c >= 0) break;
  506.       fclose (open_file);
  507.       open_file = 0;
  508.     }
  509.       else if (file_count)
  510.     {
  511.       open_file = fopen (*next_file++, "r");
  512.       file_count--;
  513.       if (!open_file)
  514.         perror_with_name (*(next_file - 1));
  515.     }
  516.       else break;
  517.     }
  518.   if (c >= 0) return c;
  519.   return getc (stdin);
  520. }
  521.  
  522. /* Unread character c on command input stream, whatever it is */
  523.  
  524. void
  525. unfetch (c)
  526.      char c;
  527. {
  528.   if (macrolevel)
  529.     macroindex[macrolevel-1]--;
  530.   else if (open_file)
  531.     ungetc (c, open_file);
  532.   else
  533.     ungetc (c, stdin);
  534. }
  535.  
  536. /* Begin execution of macro m.  */
  537.  
  538. void
  539. pushmacro (m)
  540.      decimal m;
  541. {
  542.   while (macrolevel &&
  543.         LENGTH (macrostack[macrolevel-1]) == macroindex[macrolevel-1])
  544.     popmacro();
  545.   if (m->after == STRING)
  546.     {
  547.       if (macrolevel == macrostacksize)
  548.     {
  549.       macrostacksize *= 2;
  550.       macrostack = (decimal *) xrealloc (macrostack, macrostacksize * sizeof (decimal));
  551.       macroindex = (int *) xrealloc (macroindex, macrostacksize * sizeof (int));
  552.     }
  553.       macroindex[macrolevel] = 0;
  554.       macrostack[macrolevel++] = m;
  555.       incref (m);
  556.     }
  557.   else
  558.     {   /* Number supplied as a macro!  */
  559.       push (m);   /* Its effect wouyld be to push the number.  */
  560.     }
  561. }
  562.  
  563. /* Pop a specified number of levels of macro execution.
  564.  The number of levels is specified by a decimal number d.  */
  565.  
  566. void
  567. popmacros (d)
  568.      decimal d;
  569. {
  570.   int num_pops = decimal_to_int (d);
  571.   int i;
  572.   for (i = 0; i < num_pops; i++)
  573.     popmacro ();
  574. }
  575. /* Exit one level of macro execution.  */
  576.  
  577. void
  578. popmacro ()
  579. {
  580.   if (!macrolevel)
  581.     exit (0);
  582.   else
  583.     {
  584.       decref (macrostack[--macrolevel]);
  585.     }
  586. }
  587.  
  588. void
  589. push (d)
  590.      decimal d;
  591. {
  592.   if (stacktop == stacksize - 1)
  593.     stack = (decimal *) xrealloc (stack, (stacksize *= 2) * sizeof (decimal));
  594.  
  595.     incref (d);
  596.  
  597.     stack[++stacktop] = d;
  598. }
  599.  
  600. /* Reference counting and storage freeing */
  601.  
  602. void
  603. decref (d)
  604.      decimal d;
  605. {
  606.   if (!--d->refcnt)
  607.     free (d);
  608. }
  609.  
  610. void
  611. incref (d)
  612.      decimal d;
  613. {
  614.   d->refcnt++;
  615. }
  616.  
  617. empty ()
  618. {
  619.   error ("stack empty", 0);
  620. }
  621.  
  622. regstack
  623. get_regstack ()
  624. {
  625.   if (freeregstacks)
  626.     {
  627.       regstack r = freeregstacks;
  628.       freeregstacks = r ->rest;
  629.       return r;
  630.     }
  631.   else
  632.     return (regstack) xmalloc (sizeof (struct regstack));
  633. }
  634.  
  635. void
  636. free_regstack (r)
  637.      regstack r;
  638. {
  639.   r->rest = freeregstacks;
  640.   freeregstacks = r;
  641. }
  642.  
  643. void
  644. pushreg (c)
  645.      char c;
  646. {
  647.   regstack r = get_regstack ();
  648.  
  649.   r->rest = regstacks[c];
  650.   r->value = regs[c];
  651.   regstacks[c] = r;
  652.   regs[c] = 0;
  653. }
  654.  
  655. /* Input of numbers and strings */
  656.  
  657. /* Return a character read from the terminal.  */
  658.  
  659. fgetchar ()
  660. {
  661.   return getchar ();
  662. }
  663.  
  664. void
  665. fputchar (c)
  666.      char (c);
  667. {
  668.   putchar (c);
  669. }
  670.  
  671. /* Read text from command input source up to a close-bracket,
  672.    make a string out of it, and return it.
  673.    If STARTC is nonzero, then it and STOPC must balance when nested.  */
  674.  
  675. decimal
  676. read_string (stopc, inputfn, startc)
  677.      char stopc;
  678.      int (*inputfn) ();
  679.      int startc;
  680. {
  681.   int c;
  682.   decimal result;
  683.   int i = 0;
  684.   int count = 0;
  685.  
  686.   while (1)
  687.     {
  688.       c = inputfn ();
  689.       if (c < 0 || (c == stopc && count == 0))
  690.     {
  691.       if (count != 0)
  692.         error ("Unmatched `%c'", startc);
  693.       break;
  694.     }
  695.       if (c == stopc)
  696.     count--;
  697.       if (c == startc)
  698.     count++;
  699.       if (i + 1 >= bufsize)
  700.     buffer = (char *) xrealloc (buffer, bufsize *= 2);
  701.       buffer[i++] = c;
  702.     }
  703.   result = make_decimal (i, 0);
  704.   result->after = -1;    /* Mark it as a string */
  705.   result->before++;    /* but keep the length unchanged */
  706.   bcopy (buffer, result->contents, i);
  707.   return result;
  708. }
  709.  
  710. /* Read a number from the current input source */
  711.  
  712. decimal
  713. dec_read ()
  714. {
  715.   int c;
  716.   int i = 0;
  717.  
  718.   while (1)
  719.     {
  720.       c = fetch ();
  721.       if (! ((c >= '0' && c <= '9')
  722.          || (c >= 'A' && c <= 'F')
  723.          || c == '.'))
  724.         break;
  725.       if (i + 1 >= bufsize)
  726.     buffer = (char *) xrealloc (buffer, bufsize *= 2);
  727.       buffer[i++] = c;
  728.     }
  729.   buffer[i++] = 0;
  730.   unfetch (c);
  731.  
  732.   return decimal_parse (buffer, ibase);
  733. }
  734.  
  735. /* Output of numbers and strings */
  736.  
  737. /* Print the contents of obj, either numerically or as a string,
  738.  according to what obj says it is.  */
  739.  
  740. void
  741. print_obj (obj)
  742.      decimal obj;
  743. {
  744.   if (obj->after == STRING)
  745.     print_string (obj);
  746.   else
  747.     decimal_print (obj, fputchar, obase);
  748. }
  749.  
  750. /* Print the contents of the decimal number `string', treated as a string.  */
  751.  
  752. void
  753. print_string (string)
  754.      decimal string;
  755. {
  756.   char *p = string->contents;
  757.   int len = LENGTH (string);
  758.   int i;
  759.  
  760.   for (i = 0; i < len; i++)
  761.     {
  762.       putchar (*p++);
  763.     }
  764. }
  765.  
  766. /* Set the input radix from the value of the decimal number d, if valid.  */
  767.  
  768. void
  769. setibase (d)
  770.      decimal d;
  771. {
  772.   int value = decimal_to_int (d);
  773.   if (value < 2 || value > 36)
  774.     error ("input radix must be from 2 to 36", 0);
  775.   else
  776.     ibase = value;
  777. }
  778.  
  779. /* Set the output radix from the value of the decimal number d, if valid.  */
  780.  
  781. void
  782. setobase (d)
  783.      decimal d;
  784. {
  785.   int value = decimal_to_int (d);
  786.   if (value < 2 || value > 36)
  787.     error ("output radix must be from 2 to 36", 0);
  788.   else
  789.     obase = value;
  790. }
  791.  
  792. /* Set the precision for mul and div from the value of the decimal number d, if valid.  */
  793.  
  794. void
  795. setprecision (d)
  796.      decimal d;
  797. {
  798.   int value = decimal_to_int (d);
  799.   if (value < 0 || value > 30000)
  800.     error ("precision must be nonnegative and < 30000", 0);
  801.   else
  802.     precision = value;
  803. }
  804.  
  805. /* Push the number of digits in decimal number d, as a decimal number.  */
  806.  
  807. void
  808. pushlength (d)
  809.      decimal d;
  810. {
  811.   push (decimal_from_int (LENGTH (d)));
  812. }
  813.  
  814. /* Push the number of fraction digits in d.  */
  815.  
  816. void
  817. pushscale (d)
  818.      decimal d;
  819. {
  820.   push (decimal_from_int (d->after));
  821. }
  822.  
  823. /* Push the square root of decimal number d.  */
  824.  
  825. void
  826. pushsqrt (d)
  827.      decimal d;
  828. {
  829.   push (decimal_sqrt (d, precision));
  830. }
  831.  
  832. /* Print error message and exit.  */
  833.  
  834. fatal (s1, s2)
  835.      char *s1, *s2;
  836. {
  837.   error (s1, s2);
  838.   exit (1);
  839. }
  840.  
  841. /* Print error message.  `s1' is printf control string, `s2' is arg for it. */
  842.  
  843. error (s1, s2)
  844.      char *s1, *s2;
  845. {
  846.   printf ("dc: ");
  847.   printf (s1, s2);
  848.   printf ("\n");
  849. }
  850.  
  851. decimal_error (s1, s2)
  852.      char *s1, *s2;
  853. {
  854.   error (s1, s2);
  855. }
  856.  
  857. perror_with_name (name)
  858.      char *name;
  859. {
  860.   extern int errno, sys_nerr;
  861.   extern char *sys_errlist[];
  862.   char *s;
  863.  
  864.   if (errno < sys_nerr)
  865.     s = concat ("", sys_errlist[errno], " for %s");
  866.   else
  867.     s = "cannot open %s";
  868.   error (s, name);
  869. }
  870.  
  871. /* Return a newly-allocated string whose contents concatenate those of s1, s2, s3.  */
  872.  
  873. char *
  874. concat (s1, s2, s3)
  875.      char *s1, *s2, *s3;
  876. {
  877.   int len1 = strlen (s1), len2 = strlen (s2), len3 = strlen (s3);
  878.   char *result = (char *) xmalloc (len1 + len2 + len3 + 1);
  879.  
  880.   strcpy (result, s1);
  881.   strcpy (result + len1, s2);
  882.   strcpy (result + len1 + len2, s3);
  883.   *(result + len1 + len2 + len3) = 0;
  884.  
  885.   return result;
  886. }
  887.  
  888. /* Like malloc but get fatal error if memory is exhausted.  */
  889.  
  890. int
  891. xmalloc (size)
  892.      int size;
  893. {
  894.   int result = malloc (size);
  895.   if (!result)
  896.     fatal ("virtual memory exhausted", 0);
  897.   return result;
  898. }
  899.  
  900. int
  901. xrealloc (ptr, size)
  902.      char *ptr;
  903.      int size;
  904. {
  905.   int result = realloc (ptr, size);
  906.   if (!result)
  907.     fatal ("virtual memory exhausted");
  908.   return result;
  909. }
  910.